package com.tools.common.object.json;

import cn.hutool.core.date.DateTime;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.tools.common.container.*;
import com.tools.common.container.r.*;
import com.tools.common.object.DateKit;
import com.tools.common.object.Note;
import com.tools.common.object.ObjKit;
import com.tools.common.object.string.VerifyKit;
import com.tools.web.interceptor.auth.MultiAuthUser;
import com.tools.web.interceptor.auth.SingleAuthUser;

import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;

/**
 * Jackson 的自定义反序列化器处理器工具类
 * */
@Note("Jackson 的自定义反序列化器处理器工具类")
public class DeserializerHandler {

    protected DeserializerHandler() {}

    @Note("若是混合类似的数组，那么转为 TreeSet 类型时")
    private static Comparator C;

    @Note("懒加载默认的 Comparator 比较器")
    public static Comparator getDefaultComparator() {
        if(C != null) return C;
        synchronized (DeserializerHandler.class) {
            if(C != null) return C;
            C = (o1, o2) -> 1;
            return C;
        }
    }

    /* *******************************************************************************************
     *
     *          返回所有的反序列化器
     *
     * *******************************************************************************************
     * */

    @Note("获取所有的 StdDeserializer 反序列化器")
    public static Map<Class, StdDeserializer> all() {
        Map<Class, StdDeserializer> map = new HashMap<>((int) (29/0.75) + 1);
        //日期时间
        map.put(LocalDateTime.class, localDateTimeDeserializer());
        map.put(LocalDate.class, localDateDeserializer());
        map.put(LocalTime.class, localTimeDeserializer());
        map.put(Date.class, dateDeserializer());
        map.put(java.sql.Date.class, sqlDateDeserializer());
        map.put(Timestamp.class, timestampDeserializer());
        map.put(DateTime.class, huToolDateTimeDeserializer());

        //自定义键值对容器
        StdDeserializer<OwnMap> ownMapStdDeserializer = ownMapDeserializer();
        map.put(OwnPairs.class, ownMapStdDeserializer);
        map.put(AbsOwnPair.class, ownMapStdDeserializer);
        map.put(OwnMap.class, ownMapStdDeserializer);
        map.put(OwnPair.class, ownPairDeserializer());
        map.put(JsonPair.class, jsonPairDeserializer());
        //只读键值对容器
        map.put(OnlyReadHashMap.class, onlyReadHashMapDeserializer());
        map.put(OnlyReadLinkedMap.class, onlyReadLinkedMapDeserializer());
        map.put(OnlyReadTreeMap.class, onlyReadTreeMapDeserializer());

        //自定义集合容器
        StdDeserializer<OwnList> ownListStdDeserializer = ownListDeserializer();
        map.put(OwnRows.class, ownListStdDeserializer);
        map.put(AbsOwnList.class, ownListStdDeserializer);
        map.put(OwnList.class, ownListStdDeserializer);
        StdDeserializer<OwnSet> ownSetStdDeserializer = ownSetDeserializer();
        map.put(AbsOwnSet.class, ownSetStdDeserializer);
        map.put(OwnSet.class, ownSetStdDeserializer);
        //只读集合容器
        map.put(OnlyReadArrayList.class, onlyReadArrayListDeserializer());
        map.put(OnlyReadHashSet.class, onlyReadHashSetDeserializer());
        map.put(OnlyReadLinkedSet.class, onlyReadLinkedSetDeserializer());
        map.put(OnlyReadTreeSet.class, onlyReadTreeSetDeserializer());

        //AuthUser
        map.put(SingleAuthUser.class, singleAuthUserDeserializer());
        map.put(MultiAuthUser.class, multiAuthUserDeserializer());
        //Properties
        map.put(Properties.class, propertiesDeserializer());
        //TreeSet 与 ConcurrentSkipListSet
        map.put(TreeSet.class, treeSetDeserializer());
        map.put(ConcurrentSkipListSet.class, concurrentSkipListSetDeserializer());

        return map;
    }

    /* *******************************************************************************************
     *
     *          日期的反序列化
     *
     * *******************************************************************************************
     * */


    @Note("jdk1.8 的日期时间类 LocalDateTime，如果目标字段值不是时间戳请注意日期时间格式为：yyyy-MM-dd HH:mm:ss")
    public static StdDeserializer<LocalDateTime> localDateTimeDeserializer() {
        return new StdDeserializer<LocalDateTime>(LocalDateTime.class) {
            @Override
            public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                String time = jsonParser.getText();
                if(VerifyKit.isInteger(time)) {
                    return DateKit.localDateTime(Long.parseLong(time));
                }
                if(JsonKit.DEFAULT_DATETIME_FORMATTER == null) {
                    throw new ClassCastException("无法将 【" + time + "】 转为 LocalDateTime 对象。因为默认格式化工具设置为了时间戳（timestamp）");
                }
                return LocalDateTime.parse(time, JsonKit.DEFAULT_DATETIME_FORMATTER);
            }
        };
    }


    @Note("jdk1.8 的日期类 LocalDate，如果目标字段值不是时间戳请注意日期时间格式为：yyyy-MM-dd")
    public static StdDeserializer<LocalDate> localDateDeserializer() {
        return new StdDeserializer<LocalDate>(LocalDate.class) {
            @Override
            public LocalDate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                String time = jsonParser.getText();
                if(VerifyKit.isInteger(time)) {
                    return DateKit.localDate(Long.parseLong(time));
                }
                if(JsonKit.DEFAULT_DATE_FORMATTER == null) {
                    throw new ClassCastException("无法将 【" + time + "】 转为 LocalDate 对象。因为默认格式化工具设置为了时间戳（timestamp）");
                }
                return LocalDate.parse(time, JsonKit.DEFAULT_DATE_FORMATTER);
            }
        };
    }

    @Note("jdk1.8 的时间类 LocalTime，如果目标字段值不是时间戳请注意日期时间格式为：HH:mm:ss")
    public static StdDeserializer<LocalTime> localTimeDeserializer() {
        return new StdDeserializer<LocalTime>(LocalTime.class) {
            @Override
            public LocalTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                String time = jsonParser.getText();
                if(VerifyKit.isInteger(time)) {
                    return DateKit.localTime(Long.parseLong(time));
                }
                if(JsonKit.DEFAULT_TIME_FORMATTER == null) {
                    throw new ClassCastException("无法将 【" + time + "】 转为 LocalTime 对象。因为默认格式化工具设置为了时间戳（timestamp）");
                }
                return LocalTime.parse(time, JsonKit.DEFAULT_TIME_FORMATTER);
            }
        };
    }


    @Note("Date 对象，根据字符串兼容时间戳或者日期时间字符串的转换，" +
            "如果目标字段值不是时间戳请注意日期时间格式为：yyyy-MM-dd HH:mm:ss")
    public static StdDeserializer<Date> dateDeserializer() {
        return new StdDeserializer<Date>(Date.class) {
            @Override
            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                String time = jsonParser.getText();
                if(VerifyKit.isInteger(time)) {
                    return new Date(Long.parseLong(time));
                }
                if(JsonKit.DEFAULT_DATETIME_FORMATTER == null) {
                    throw new ClassCastException("无法将 【" + time + "】 转为 java.util.Date 对象，因为默认格式化工具设置为了时间戳（timestamp）");
                }
                return DateKit.date(time, JsonKit.DEFAULT_DATETIME_FORMATTER);
            }
        };
    }


    @Note("sql 包的 Date 对象，根据字符串兼容时间戳或者日期时间字符串的转换，" +
            "如果目标字段值不是时间戳请注意日期时间格式为：yyyy-MM-dd HH:mm:ss")
    public static StdDeserializer<java.sql.Date> sqlDateDeserializer() {
        return new StdDeserializer<java.sql.Date>(java.sql.Date.class) {
            @Override
            public java.sql.Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                String time = jsonParser.getText();
                if(VerifyKit.isInteger(time)) {
                    return new java.sql.Date(Long.parseLong(time));
                }
                if(JsonKit.DEFAULT_DATETIME_FORMATTER == null) {
                    throw new ClassCastException("无法将 【" + time + "】 转为 java.sql.Date 对象，因为默认格式化工具设置为了时间戳（timestamp）");
                }
                Date date = DateKit.date(time, JsonKit.DEFAULT_DATETIME_FORMATTER);
                return new java.sql.Date(date.getTime());
            }
        };
    }

    @Note("sql 包的 Timestamp 对象，根据字符串兼容时间戳或者日期时间字符串的转换，" +
            "如果目标字段值不是时间戳请注意日期时间格式为：yyyy-MM-dd HH:mm:ss")
    public static StdDeserializer<Timestamp> timestampDeserializer() {
        return new StdDeserializer<Timestamp>(Timestamp.class) {
            @Override
            public Timestamp deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                String time = jsonParser.getText();
                if(VerifyKit.isInteger(time)) {
                    return new Timestamp(Long.parseLong(time));
                }
                if(JsonKit.DEFAULT_DATETIME_FORMATTER == null) {
                    throw new ClassCastException("无法将 【" + time + "】 转为 java.sql.Timestamp 对象，因为默认格式化工具设置为了时间戳（timestamp）");
                }
                Date date = DateKit.date(time, JsonKit.DEFAULT_DATETIME_FORMATTER);
                return new Timestamp(date.getTime());
            }
        };
    }


    @Note("cn.hutool.core.date 包的 DateTime 对象，根据字符串兼容时间戳或者日期时间字符串的转换，" +
            "如果目标字段值不是时间戳请注意日期时间格式为：yyyy-MM-dd HH:mm:ss")
    public static StdDeserializer<DateTime> huToolDateTimeDeserializer() {
        return new StdDeserializer<DateTime>(DateTime.class) {
            @Override
            public DateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                String time = jsonParser.getText();
                if(VerifyKit.isInteger(time)) {
                    return new DateTime(Long.parseLong(time));
                }
                if(JsonKit.DEFAULT_DATETIME_FORMATTER == null) {
                    throw new ClassCastException("无法将 【" + time + "】 转为 cn.hutool.core.date.DateTime 对象，因为默认格式化工具设置为了时间戳（timestamp）");
                }
                return new DateTime(time, JsonKit.DEFAULT_DATETIME_FORMATTER);
            }
        };
    }

    /* *******************************************************************************************
     *
     *          键值对容器
     *
     * *******************************************************************************************
     * */

    @Note("处理、转换获取 OwnMap 自定义键值对容器实例")
    public static StdDeserializer<OwnMap> ownMapDeserializer() {
        return new StdDeserializer<OwnMap>(OwnMap.class) {
            @Override
            public OwnMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    OwnMap<String, Object> ownMap = new OwnMap<>(MapEnum.LINKED);
                    JsonKit.default_pairsParseToken(jsonParser, ownMap);
                    return ownMap;
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.OwnMap 实例");
            }
        };
    }


    @Note("处理、转换获取 OwnPair 自定义键值对容器实例")
    public static StdDeserializer<OwnPair> ownPairDeserializer() {
        return new StdDeserializer<OwnPair>(OwnPair.class) {
            @Override
            public OwnPair deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    OwnPair ownPair = new OwnPair(MapEnum.LINKED);
                    JsonKit.default_pairsParseToken(jsonParser, ownPair);
                    return ownPair;
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.OwnPair 实例");
            }
        };
    }


    @Note("处理、转换获取 JsonPair 自定义键值对容器实例")
    public static StdDeserializer<JsonPair> jsonPairDeserializer() {
        return new StdDeserializer<JsonPair>(JsonPair.class) {
            @Override
            public JsonPair deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    JsonPair jsonPair = new JsonPair();
                    JsonKit.default_pairsParseToken(jsonParser, jsonPair);
                    return jsonPair;
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.JsonPair 实例");
            }
        };
    }


    @Note("处理、转换获取 OnlyReadHashMap 只读 HashMap 实例")
    public static StdDeserializer<OnlyReadHashMap> onlyReadHashMapDeserializer() {
        return new StdDeserializer<OnlyReadHashMap>(OnlyReadHashMap.class) {
            @Override
            public OnlyReadHashMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    HashMap map = new HashMap<>();
                    JsonKit.default_mapParseToken(jsonParser, map);
                    return new OnlyReadHashMap<>(map);
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadHashMap 实例");
            }
        };
    }


    @Note("处理、转换获取 OnlyReadLinkedMap 只读 LinkedHashMap 实例")
    public static StdDeserializer<OnlyReadLinkedMap> onlyReadLinkedMapDeserializer() {
        return new StdDeserializer<OnlyReadLinkedMap>(OnlyReadLinkedMap.class) {
            @Override
            public OnlyReadLinkedMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    LinkedHashMap map = new LinkedHashMap<>();
                    JsonKit.default_mapParseToken(jsonParser, map);
                    return new OnlyReadLinkedMap<>(map);
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadTreeMap 实例");
            }
        };
    }


    @Note("处理、转换获取 OnlyReadTreeMap 只读 TreeMap 实例")
    public static StdDeserializer<OnlyReadTreeMap> onlyReadTreeMapDeserializer() {
        return new StdDeserializer<OnlyReadTreeMap>(OnlyReadLinkedMap.class) {
            @Override
            public OnlyReadTreeMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    TreeMap map = new TreeMap<>();
                    JsonKit.default_mapParseToken(jsonParser, map);
                    return new OnlyReadTreeMap<>(map);
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadTreeMap 实例");
            }
        };
    }

    @Note("处理、转换获取 Properties 实例")
    public static StdDeserializer<Properties> propertiesDeserializer() {
        return new StdDeserializer<Properties>(Properties.class) {
            @Override
            public Properties deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    Properties properties = new Properties();
                    JsonKit.default_mapParseToken(jsonParser, properties);
                    return properties;
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 java.util.Properties 实例");
            }
        };
    }


    /* *******************************************************************************************
     *
     *          集合
     *
     * *******************************************************************************************
     * */

    @Note("处理、转换获取自定义容器实例 OwnList")
    public static StdDeserializer<OwnList> ownListDeserializer() {
        return new StdDeserializer<OwnList>(OwnList.class) {
            @Override
            public OwnList deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_ARRAY) {
                    OwnList ownList = new OwnList<>();
                    JsonKit.default_ownRowParseToken(jsonParser, ownList);
                    return ownList;
                }
                throw new ClassCastException("无法将对象类型的 JSON 字符串转为 com.tools.common.container.OwnList 实例");
            }
        };
    }


    @Note("处理、转换获取自定义容器实例 OwnSet")
    public static StdDeserializer<OwnSet> ownSetDeserializer() {
        return new StdDeserializer<OwnSet>(OwnSet.class) {
            @Override
            public OwnSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_ARRAY) {
                    OwnSet ownSet = new OwnSet<>();
                    JsonKit.default_ownRowParseToken(jsonParser, ownSet);
                    return ownSet;
                }
                throw new ClassCastException("无法将对象类型的 JSON 字符串转为 com.tools.common.container.OwnList 实例");
            }
        };
    }


    @Note("处理、转换获取只读的 ArrayList 实例 OnlyReadArrayList")
    public static StdDeserializer<OnlyReadArrayList> onlyReadArrayListDeserializer() {
        return new StdDeserializer<OnlyReadArrayList>(OnlyReadArrayList.class) {
            @Override
            public OnlyReadArrayList deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_ARRAY) {
                    List list = new ArrayList<>();
                    JsonKit.default_collectionParseToken(jsonParser, list);
                    return new OnlyReadArrayList<>(list);
                }
                throw new ClassCastException("无法将对象类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadArrayList 实例");
            }
        };
    }


    @Note("处理、转换获取只读的 HashSet 实例 OnlyReadHashSet")
    public static StdDeserializer<OnlyReadHashSet> onlyReadHashSetDeserializer() {
        return new StdDeserializer<OnlyReadHashSet>(OnlyReadHashSet.class) {
            @Override
            public OnlyReadHashSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_ARRAY) {
                    Set set = new HashSet<>();
                    JsonKit.default_collectionParseToken(jsonParser, set);
                    return new OnlyReadHashSet<>(set);
                }
                throw new ClassCastException("无法将对象类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadHashSet 实例");
            }
        };
    }


    @Note("处理、转换获取只读的 LinkedHashSet 实例 OnlyReadLinkedSet")
    public static StdDeserializer<OnlyReadLinkedSet> onlyReadLinkedSetDeserializer() {
        return new StdDeserializer<OnlyReadLinkedSet>(OnlyReadHashSet.class) {
            @Override
            public OnlyReadLinkedSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_ARRAY) {
                    Set set = new LinkedHashSet<>();
                    JsonKit.default_collectionParseToken(jsonParser, set);
                    return new OnlyReadLinkedSet<>(set);
                }
                throw new ClassCastException("无法将对象类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadLinkedSet 实例");
            }
        };
    }


    @Note("处理、转换获取只读的 TreeSet 实例 OnlyReadTreeSet")
    public static StdDeserializer<OnlyReadTreeSet> onlyReadTreeSetDeserializer() {
        return new StdDeserializer<OnlyReadTreeSet>(OnlyReadTreeSet.class) {
            @Override
            public OnlyReadTreeSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_ARRAY) {
                    Set set = new HashSet<>();
                    try {
                        JsonKit.default_collectionParseToken(jsonParser, set);
                        return new OnlyReadTreeSet<>(set);
                    } catch (ClassCastException e) {
                        JsonKit.default_collectionParseToken(jsonParser, set);
                        return new OnlyReadTreeSet<>(getDefaultComparator(), set);
                    }
                }
                throw new ClassCastException("无法将对象类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadTreeSet 实例");
            }
        };
    }


    @Note("处理、转换获取 TreeSet 实例")
    public static StdDeserializer<TreeSet> treeSetDeserializer() {
        return new StdDeserializer<TreeSet>(TreeSet.class) {
            @Override
            public TreeSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_ARRAY) {
                    TreeSet set = new TreeSet<>();
                    try {
                        JsonKit.default_collectionParseToken(jsonParser, set);
                        return set;
                    } catch (ClassCastException e) {
                        TreeSet treeSet = new TreeSet(getDefaultComparator());
                        treeSet.addAll(set);
                        JsonKit.default_collectionParseToken(jsonParser, treeSet);
                        return treeSet;
                    }
                }
                throw new ClassCastException("无法将对象类型的 JSON 字符串转为 java.util.TreeSet 实例");
            }
        };
    }


    @Note("处理、转换获取 ConcurrentSkipListSet 实例")
    public static StdDeserializer<ConcurrentSkipListSet> concurrentSkipListSetDeserializer() {
        return new StdDeserializer<ConcurrentSkipListSet>(ConcurrentSkipListSet.class) {
            @Override
            public ConcurrentSkipListSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_ARRAY) {
                    ConcurrentSkipListSet set = new ConcurrentSkipListSet<>();
                    try {
                        JsonKit.default_collectionParseToken(jsonParser, set);
                        return set;
                    } catch (ClassCastException e) {
                        ConcurrentSkipListSet treeSet = new ConcurrentSkipListSet(getDefaultComparator());
                        treeSet.addAll(set);
                        JsonKit.default_collectionParseToken(jsonParser, treeSet);
                        return treeSet;
                    }
                }
                throw new ClassCastException("无法将对象类型的 JSON 字符串转为 java.util.concurrent.ConcurrentSkipListSet 实例");
            }
        };
    }

    /* *******************************************************************************************
     *
     *          AuthUser 的反序列化器
     *
     * *******************************************************************************************
     * */

    @Note("SingleAuthUser 类的自定义反序列化逻辑")
    public static StdDeserializer<SingleAuthUser> singleAuthUserDeserializer() {
        return new StdDeserializer<SingleAuthUser>(SingleAuthUser.class) {
            @Override
            public SingleAuthUser deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonNode jsonNode = JsonKit.readToNode(jsonParser);
                String userJson = ObjKit.toStringNullValue(jsonNode.path("user").toString());
                String userTypeClassname = jsonNode.path("userTypeClass").asText();
                Class<?> objectClass = ObjKit.getObjectClass(userTypeClassname);
                Object user = JsonKit.toEntity(userJson, objectClass);
                Map roleKeyMap = JsonKit.toEntity(jsonNode.path("roleKeyMap").toString(), HashMap.class);
                Map permissionKeyMap = JsonKit.toEntity(jsonNode.path("permissionKeyMap").toString(), HashMap.class);
                List routerList = JsonKit.toEntity(jsonNode.path("routerList").toString(), ArrayList.class);
                Map customData = JsonKit.toEntity(jsonNode.path("customData").toString(), HashMap.class);
                String uuid = jsonNode.path("uuid").asText();
                String deviceTypeId = jsonNode.path("deviceTypeId").asText();
                String userType = jsonNode.path("userType").asText();
                Object userId = ObjKit.stringToRealValue(jsonNode.path("userId").asText());
                SingleAuthUser authUser = new SingleAuthUser(userId, user, roleKeyMap, permissionKeyMap, routerList);
                authUser.setUserTypeClass(userTypeClassname);
                authUser.setUuid(uuid);
                authUser.setDeviceTypeId(deviceTypeId);
                authUser.setUserType(userType);
                authUser.putAllData(customData);
                return authUser;
            }
        };
    }




    @Note("MultiAuthUser 类的自定义反序列化逻辑")
    public static StdDeserializer<MultiAuthUser> multiAuthUserDeserializer() {
        return new StdDeserializer<MultiAuthUser>(MultiAuthUser.class) {
            @Override
            public MultiAuthUser deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonNode jsonNode = JsonKit.readToNode(jsonParser);
                String userTypeClassname = jsonNode.path("userTypeClass").asText();
                String userJson = ObjKit.toStringNullValue(jsonNode.path("user").toString());
                Class<?> objectClass = ObjKit.getObjectClass(userTypeClassname);
                Object user = JsonKit.toEntity(userJson, objectClass);
                List routerList = JsonKit.toEntity(jsonNode.path("routerList").toString(), ArrayList.class);
                Map customData = JsonKit.toEntity(jsonNode.path("customData").toString(), HashMap.class);
                Map roleKeyMap = JsonKit.toEntity(jsonNode.path("roleKeyMap").toString(), HashMap.class);
                Map permissionKeyMap = JsonKit.toEntity(jsonNode.path("permissionKeyMap").toString(), HashMap.class);
                Object userId = ObjKit.stringToRealValue(jsonNode.path("userId").asText());
                String deviceAndLoginRecordName = "deviceAndLoginRecord";
                JsonNode loginRecordNode = jsonNode.path(deviceAndLoginRecordName);
                ConcurrentHashMap deviceAndLoginRecord = JsonKit.toEntity(loginRecordNode.toString(), ConcurrentHashMap.class);
                MultiAuthUser authUser = new MultiAuthUser(userId, user, roleKeyMap, permissionKeyMap, routerList);
                authUser.setUserTypeClass(userTypeClassname);
                authUser.putAllData(customData);
                Field field = ObjKit.getField(SingleAuthUser.class, deviceAndLoginRecordName);
                ObjKit.setFieldValue(authUser, field, deviceAndLoginRecord);
                return authUser;
            }
        };
    }
}
